package com.dayatang.exam.domain;

import java.text.Collator;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.Locale;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.dayatang.domain.AbstractEntity;
import com.dayatang.domain.QuerySettings;

@Entity
@Table(name = "users")
public class User extends AbstractEntity implements Comparable<User> {

	@Transient
	private static final long serialVersionUID = -7722509457720724740L;

	public static final String ORIGINAL_PASSWORD= "12345678";

	private String code;

	@Column(nullable = false)
	private String name;

	private String password;

	@Column(unique = true, nullable = false)
	private String idNumber;

	private String gender;

	@Temporal(TemporalType.DATE)
	private Date birthday;
	
	@ElementCollection
	@JoinTable(name = "user_roles",
			joinColumns = @JoinColumn(name = "user_id"))
	private Set<Role> roles;

	@Embedded
	private UserContactInfo contactInfo = new UserContactInfo();

	private boolean enabled = true;

	public User() {
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getIdNumber() {
		return idNumber;
	}

	public void setIdNumber(String idNumber) {
		this.idNumber = idNumber;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public UserContactInfo getContactInfo() {
		return contactInfo;
	}

	public void setContactInfo(UserContactInfo contactInfo) {
		this.contactInfo = contactInfo;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public void disable() {
		enabled = false;
		save();
	}

	public void enable() {
		enabled = true;
		save();
	}

	public static User get(Long id) {
		return getRepository().get(User.class, id);
	}

	public static User getByCode(String code) {
		return getRepository().getSingleResult(QuerySettings.create(User.class)
				.eq("code", code));
	}

	public static User getByIdNumber(String idNumber) {
		return getRepository().getSingleResult(QuerySettings.create(User.class)
				.eq("idNumber", idNumber));
	}

	public static User getByEmail(String email) {
		return getRepository().getSingleResult(QuerySettings.create(User.class)
				.eq("contactInfo.email", email));
	}

	public static Collection<User> findByName(String name) {
		return getRepository().find(QuerySettings.create(User.class)
				.eq("name", name));
	}

	public static Collection<User> listDisabled() {
		return getRepository().find(QuerySettings.create(User.class)
				.eq("enabled", false));
	}

	public static Collection<User> findDisabledByName(String name) {
		return getRepository().find(QuerySettings.create(User.class)
				.eq("enabled", false)
				.eq("name", name));
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(final Object other) {
		if (other == null || !(other instanceof User))
			return false;
		User castOther = (User) other;
/*		if (code != null && code.equals(castOther.getCode())) {
			return true;
		}
*/		if (idNumber != null && idNumber.equals(castOther.getIdNumber())) {
			return true;
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#hashCode()
	 */

	public int hashCode() {
		return new HashCodeBuilder().append(idNumber).toHashCode();
	}


	public String toString() {
		return new ToStringBuilder(this).append("id", getId()).append("code", code)
				.append("name", name).toString();
	}

	@SuppressWarnings("unchecked")
	public int compareTo(User other) {
		if (other == null) {
			return 1;
		}
		Comparator comparator = Collator.getInstance(Locale.CHINA);
		return comparator.compare(name, other.getName());
	}
}
